1、定义类，在构造函数立即执行，同时传入resolve,reject函数（使用箭头函数，不处理this指向问题）
2、定义状态，resolve\reject里面状态不可逆
3、定义保存结果和成功和失败的数组（为了延迟执行）
4、定义then函数，处理三个状态，以及处理异步任务，使用（queneMicrotask、MutationObserver、setTimeout,跟进浏览器兼容性依次判断使用）
5、改造then函数，返货实例，实现链式调用
6、定义resolvePromise函数，处理返回值是Promise和常量的情况（返回值穿透）
7、定义catch函数 8、finally函数 
---------------------------------------
实例方法： 
1、resolve函数:传入普通值返回promise实列，传入promise实列，直接返回
2、reject函数：传入普通值返回promise实列，传入promise实列，直接返回
3、race函数：第一个成功或者失败的实列
4、all函数:所有成功返回成功数组，有一个失败返回失败
5、allSettled函数:所有任务都完成，返回每个任务的状态和结果
6、any函数:第一个成功的实列，有一个成功返回成功，所有失败返回失败数组

<script>
  function asyncFunc(callback) {
    if (typeof queueMicrotask === 'function') {
      queueMicrotask(callback)
    } else if (typeof MutationObserver === 'function') {
      const observer = new MutationObserver(callback)
      observer.observe(document.body, {
        childList: true,
      })
    } else if (typeof setTimeout === 'function') {
      setTimeout(callback)
    }
  }

  function resolvePromise(promise, x, resolve, reject) {
    if (promise === x) {
      return reject(new TypeError('Chaining cycle detected for promise'))
    }
    if (x instanceof ZllPromise) {
      x.then(
        (res) => resolve(res),
        (res) => reject(res)
      )
    } else {
      resolve(x)
    }
  }

  const PENDING = 'pending'
  const FULFILLED = 'fulfilled'
  const REJECTED = 'rejected'
  class ZllPromise {
    constructor(executor) {
      this.state = PENDING
      this.result = undefined
      this.resolvesCallbacks = []
      this.rejectsCallbacks = []
      const resolve = (result) => {
        if (this.state === PENDING) {
          this.state = FULFILLED
          this.result = result
          this.resolvesCallbacks.forEach((callback) => {
            callback()
          })
        }
      }
      const reject = (result) => {
        if ((this.state = PENDING)) {
          this.state = REJECTED
          this.result = result
          this.rejectsCallbacks.forEach((callback) => {
            callback()
          })
        }
      }
      executor(resolve, reject)
    }

    then(onFulfilled, onRejected) {
      onFulfilled =
        typeof onFulfilled === 'function' ? onFulfilled : (value) => value
      onRejected =
        typeof onRejected === 'function'
          ? onRejected
          : (reason) => {
              throw reason
            }
      const promise2 = new ZllPromise((resolve, reject) => {
        if (this.state === FULFILLED) {
          asyncFunc(() => {
            try {
              const x = onFulfilled(this.result)
              resolvePromise(promise2, x, resolve, reject)
            } catch (e) {
              reject(e)
            }
          })
        }
        if (this.state === REJECTED) {
          asyncFunc(() => {
            try {
              const x = onRejected(this.result)
              resolvePromise(promise2, x, resolve, reject)
            } catch (e) {
              reject(e)
            }
          })
        }
        if (this.state === PENDING) {
          this.resolvesCallbacks.push(() => {
            asyncFunc(() => {
              try {
                const x = onFulfilled(this.result)
                resolvePromise(promise2, x, resolve, reject)
              } catch (e) {
                reject(e)
              }
            })
          })
          this.rejectsCallbacks.push(() => {
            asyncFunc(() => {
              try {
                const x = onRejected(this.result)
                resolvePromise(promise2, x, resolve, reject)
              } catch (e) {
                reject(e)
              }
            })
          })
        }
      })
      return promise2
    }

    catch(onRejected) {
      return this.then(undefined, onRejected)
    }
    finally(onFinally) {
      return this.then(onFinally, onFinally)
    }

    static resolve(value) {
      if (value instanceof ZllPromise) {
        return value
      }
      return new ZllPromise((resolve) => resolve(value))
    }

     static reject(value) {
      if (value instanceof ZllPromise) {
        return value
      }
      return new ZllPromise((resolve,reject) => reject(value))
    }

    static race(promises) {
      return new ZllPromise((resolve,reject)=>{
        if(!Array.isArray(promises)) {
          return reject(new TypeError('Argument is not iterable'))
        }
        promises.forEach((p)=>{
          ZllPromise.resolve(p).then((res)=>{
            resolve(res)
          },(err)=>{
            reject(err)
          })
        })
      })
    }

    static all(promises) {
      return new ZllPromise((resolve,reject)=>{
        if(!Array.isArray(promises)) {
           return reject(new TypeError('Argument is not iterable'))
        }
        if(promises.length === 0) {
          return resolve([])
        }
        const result = []
        let count = 0
        promises.forEach((p,index)=>{
          ZllPromise.resolve(p).then((res)=>{
            result[index] = res
            count++
            promises.length === count && resolve(result)
          },(err)=>{
            reject(err)
          })
        })
      })

    }

    static any(promises) {
      return new ZllPromise((resolve,reject)=>{
        if(!Array.isArray(promises)) {
          return reject(new TypeError('Argument is not iterable'))
        }
        if(promises.length === 0) {
          return reject(new AggregateError('All promises were rejected'))
        }
        let count = 0
        let errors = []
        promises.forEach((p,index)=>{
          ZllPromise.resolve(p).then((res)=>{
            resolve(res)
          },(err)=>{
            count++
            errors[index] = err
            if(count === promises.length) {
              reject(new AggregateError(errors))
            }
          })
        })
      })
    }

    static allSettled(promises) {
      return new ZllPromise((resolve,reject)=>{
        if(!Array.isArray(promises)) {
          return reject(new TypeError('Argument is not iterable'))
        }
        if(promises.length === 0) {
          return resolve([])
        }
        const result = []
        let count = 0
        promises.forEach((p,index)=>{
          ZllPromise.resolve(p).then((res)=>{
            result[index] = { status: FULFILLED, value: res }
            count++
            promises.length === count && resolve(result)
          },(err)=>{
            count++
            result[index] = { status: REJECTED, reason: err }
            promises.length === count && resolve(result)
          })
        })
      })
    }
  }

  // const p = new ZllPromise((resolve, reject) => {
  //   setTimeout(() => {
  //     reject(1)
  //   }, 1000)
  // })
  // p.then((res) => {
  //   console.log('res', res)
  //   return new ZllPromise((resolve, reject) => {
  //     resolve(444)
  //   })
  // })
  //   .then((res) => {
  //     console.log('res', res)
  //   })
  //   .catch((err) => {
  //     console.log('err', err)
  //   }).finally(()=>{
  //     console.log('最后执行')
  //   })

  // ZllPromise.resolve(
  //   new ZllPromise((resolve, reject) => {
  //     setTimeout(() => {
  //       reject(111)
  //     }, 1000)
  //   })
  // )
  //   .then((res) => {
  //     console.log('res->', res)
  //   })
  //   .catch((err) => {
  //     console.log('err2->', err)
  //   })


    new ZllPromise((resolve, reject) => {
    reject('失败')
  })
    .catch((err) => {
      console.log('err', err)
    })
    .finally(() => {
      console.log('finally')
    })
</script>
